﻿using DFGK_WMS.IRepository;
using DFGK_WMS.Model.DTO;
using DFGK_WMS.Model.Enum;
using DFGK_WMS.Model.Models;
using DFGK_WMS.WebAPI.AttributeFile;
using DFGK_WMS.WebAPI.Controllers.Result;
using DFGK_WMS.WebAPI.Tools;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.VisualBasic;
using NetTaste;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.XWPF.UserModel;
using OfficeOpenXml;
using System;
using System.Data;
using System.Drawing.Printing;
using System.Net.Mime;
using System.Security.Claims;
using System.Security.Cryptography;

namespace DFGK_WMS.WebAPI.Controllers.入库
{
    /// <summary>
    /// 入库
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class TReceivingOrderDetailController : ControllerBase
    {
        private readonly ILogRepository logService;
        public TReceivingOrderDetailController(ITReceivingOrderDetailRepository tReceiving,ITReceivingGoodsDetailRepository tReceivingGoodsDetailRepository, ILogRepository logService)
        {

            TReceiving = tReceiving;
            TReceivingGoodsDetailRepository = tReceivingGoodsDetailRepository;
            this.logService = logService;
        }

        public ITReceivingOrderDetailRepository TReceiving { get; }
        public ITReceivingGoodsDetailRepository TReceivingGoodsDetailRepository { get; }

        /// <summary>
        /// 添加入库
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        [HttpPost]
        [HttpIdempotent(WaitMillisecond = 10000, CacheMillisecond = 3000)]
        public IActionResult AddTReceivingOrderDetail(TReceivingOrderDetail m)
        {
            string message = "";
            if(m.Qty<=0)
            {
                return Ok(BaseResult.Result("400", "入库数量不能为0"));
            }
            var rule = TReceiving.AddTReceivingOrderDetail(m,out message);
            if (rule)
            {
                string uname = HttpContext.User.FindFirstValue("UserName");
                string runame = HttpContext.User.FindFirstValue("RealName");
                int uid = Convert.ToInt32(HttpContext.User.FindFirstValue("Id"));
                string? ip = HttpContext.Connection.RemoteIpAddress?.ToString();
                TLog logg = new TLog
                {
                    LogType = 1,
                    ActionType = 4,
                    ModuleName = "入库管理",
                    UserName = uname,
                    RealName = runame,
                    UserId = uid,
                    Description = uname + "创建了入库单" + m.OrderSn,
                    //获取前端IP地址
                    Ipaddress = ip
                };

                logService.AddTLod(logg);
                return Ok(BaseResult.Result(true, "添加成功", "200"));
            }
            return Ok(BaseResult.Result(false, message, "500"));
        }

        /// <summary>
        /// 修改状态
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        [HttpPut]
        public IActionResult UpdTReceivingOrderDetaState(ReceivingOrderDetailDto m)
        {
            if(m.Id<=0)
            {
                return Ok(BaseResult.Result("400", "Id有误！"));
            }
            bool IsOK = TReceiving.UpdTReceivingOrderDetaState(m);
            if (IsOK)
            {
                return Ok(BaseResult.Result(true, "修改成功！", "200"));
            }
            return Ok(BaseResult.Result(false, "修改失败！", "500"));
        }

        /// <summary>
        /// 删除入库单
        /// </summary>
        /// <param name="rid"></param>
        /// <returns></returns>
        [HttpDelete]
        public IActionResult DelTReceivingOrderDetail(int rid)
        {
            if (rid <= 0)
            {
                return Ok(BaseResult.Result("500", "Id有误！"));
            }
            bool IsOK = TReceiving.DelTReceivingOrderDetail(rid);
            if (IsOK)
            {
                return Ok(BaseResult.Result(true, "删除成功！", "200"));
            }
            return Ok(BaseResult.Result(false, "删除失败！", "500"));
        }
        /// <summary>
        /// 批量删除入库单
        /// </summary>
        /// <param name="rid"></param>
        /// <returns></returns>
        [HttpDelete]
        public IActionResult DelTReceivingOrderDetailList(int[] ridList)
        {
            if (ridList.Length <= 0)
            {
                return Ok(BaseResult.Result("500", "Id有误！"));
            }
            bool IsOK = true;
            foreach (var rid in ridList)
            {
                bool isOK = TReceiving.DelTReceivingOrderDetail(rid);
                string uname = HttpContext.User.FindFirstValue("UserName");
                string runame = HttpContext.User.FindFirstValue("RealName");
                int uid = Convert.ToInt32(HttpContext.User.FindFirstValue("Id"));
                string? ip = HttpContext.Connection.RemoteIpAddress?.ToString();
                TLog logg = new TLog
                {
                    LogType = 1,
                    ActionType = 4,
                    ModuleName = "入库管理",
                    UserName = uname,
                    RealName = runame,
                    UserId = uid,
                    Description = isOK ? uname + "删除了入库单" : uname+"删除入库单失败",
                    //获取前端IP地址
                    Ipaddress = ip,
                    Status = isOK ? 1 : 0,
                };
                if (!isOK)
                {
                    IsOK = false;
                    break;
                }
            }
            if (IsOK)
            {
                return Ok(BaseResult.Result(true, "删除成功！", "200"));
            }
            return Ok(BaseResult.Result(false, "删除失败！", "500"));
        }

        /// <summary>
        /// 根据Id获取对象
        /// </summary>
        /// <param name="rid"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetTReceivingOrderDetailById(int rid)
        {
            if (rid <= 0)
            {
                return Ok(BaseResult.Result("400", "Id有误！"));
            }
            var mobj = TReceiving.GetTReceivingOrderDetailById(rid);
            if (mobj != null)
            {
                return Ok(BaseResult.Result(mobj, "获取成功", "200"));
            }
            return Ok(BaseResult.Result(null, "获取失败！", "500"));
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        [HttpPut]
        public IActionResult UpdTReceivingOrderDetail(TReceivingOrderDetail m)
        {
            if(m.Id<=0)
            {
                return Ok(BaseResult.Result("400", "Id有误！"));
            }
            if (m.Qty <= 0)
            {
                return Ok(BaseResult.Result("400", "入库数量不能为0"));
            }
            //if(m.Status!=0)
            //{
            //    return Ok(BaseResult.Result("200", "只有状态为创建的入库单才能修改"));
            //}
            string message = "";
            var rule = TReceiving.UpdTReceivingOrderDetail(m,out message);
            if (rule)
            {
                string uname = HttpContext.User.FindFirstValue("UserName");
                string runame = HttpContext.User.FindFirstValue("RealName");
                int uid = Convert.ToInt32(HttpContext.User.FindFirstValue("Id"));
                string? ip = HttpContext.Connection.RemoteIpAddress?.ToString();
                TLog logg = new TLog();
                logg.LogType = 1;
                logg.ActionType = 6;
                logg.ModuleName = "入库管理";
                logg.UserName = uname;
                logg.RealName = runame;
                logg.UserId = uid;
                logg.Description = uname + "修改了入库单" + m.OrderSn;
                //获取前端IP地址
                logg.Ipaddress = ip;

                logService.AddTLod(logg);
                return Ok(BaseResult.Result(true, "修改成功", "200"));
            }
            return Ok(BaseResult.Result(false, message, "500"));
        }

        /// <summary>
        /// 显示入库单列表
        /// </summary>
        /// <param name="billType"></param>
        /// <param name="status"></param>
        /// <param name="warehouseid"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalCount"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetReceivingOrderDetailList(DateTime? startTime, DateTime? endTime, string? orderSn, int billType, int status, int warehouseid, int pageIndex, int pageSize)
        {
            if(pageIndex<=0 || pageSize<=0)
            {
                return Ok(BaseResult.Result("400", "分页参数有误！"));
            }
            int totalCount;

            var list = TReceiving.GetReceivingOrderDetailList(startTime, endTime,orderSn, billType, status, warehouseid, pageIndex, pageSize, out totalCount);

            if (list != null)
            {
                return Ok(BaseResult.Result(list, "查询成功！", "200", totalCount));
            }
            return Ok(BaseResult.Result(null, "查询失败！", "500", 0));
        }

        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="orderSn"></param>
        /// <param name="billType"></param>
        /// <param name="status"></param>
        /// <param name="warehouseid"></param>
        /// <returns></returns>
        [HttpGet]
        public FileContentResult ExportToExcel(DateTime? startTime, DateTime? endTime, string? orderSn, int billType, int status, int warehouseid)
        {
            //物料代码 物料描述 单号 ；单据类型 货主 批次号 小批次 任务数量 实际收货数量 计量单位 已组垛数量 订单来源 创建用户 创建时间
            int totalCount;
            var list = TReceiving.GetReceivingOrderDetailList(startTime,endTime,orderSn, billType, status, warehouseid,1, int.MaxValue, out totalCount);
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>()
            {
                {"MaterialCode", "物料代码" },
                {"MaterialName", "物料描述" },
                {"OrderSn", "入库单编号" },
                {"LocationName","仓位名称" },
                {"PalletBarcode", "垛条码" },
                {"BillType", "单据类型" },
                {"Status", "单据状态" },
                {"BatchNo", "批次" },
                {"SmallBatchNo", "详细批次" },
                {"Qty", "数量" },
                {"SourceType","订单来源" },
                {"CreateUserName","用户" },
                {"CreateDate","入库时间" }
            };
            //直接匿名对象就好
            var exList = list.Select(s => new
            {
                BillType = ExBilTypeMapper(s.BillType),
                s.MaterialCode,
                s.MaterialName,
                Qty=(int)s.Qty.GetValueOrDefault(),
                s.BatchNo,
                s.SmallBatchNo,
                s.LocationCode,
                s.LocationName,
                s.PalletBarcode,
                s.CreateDate,
                Status = ExStatusMapper(s.Status),
                SourceType = ExSourceTypeMapper(s.SourceType),
                s.CreateUserName
            }).ToList();

            var fileBytes = Utils.ExportToExcel(exList, keyValuePairs);
            return File(fileBytes, MediaTypeNames.Application.Octet, "入库管理.xlsx");
        }
        //状态转换
        private string ExStatusMapper(int status)
        {
            //0 - 新建; 1 - 已启动; 2 - 作业中; 3 - 已完成; 4 - 强制完成; 5 - 暂停; 6 - 失效；7 - 异常
            if (status == 0)
            {
                return "新建";
            }
            if (status == 1)
            {
                return "已启动";
            }
            if (status == 2)
            {
                return "作业中";
            }
            if (status == 3)
            {
                return "已完成";
            }
            if (status == 4)
            {
                return "强制完成";
            }
            if (status == 5)
            {
                return "暂停";
            }
            if (status == 6)
            {
                return "失效";
            }
            if (status == 7)
            {
                return "异常";
            }
            return "";
        }
        private string ExSourceTypeMapper(int? sourceType)
        {
            switch (sourceType.GetValueOrDefault())
            {
                case 0:
                    return "手工建单";
                case 1:
                    return "ERP";
                case 2:
                    return "MES";
                case 3:
                    return "SAP";
                case 4:
                    return "回流入库";
                default:
                    return "";
            }
        }
        private string ExBilTypeMapper(int? bilType)
        {
            switch (bilType.GetValueOrDefault())
            {
                case 1:
                    return "本地入库";
                case 2:
                    return "生产订单入库";
                case 3:
                    return "采购订单入库";
                case 4:
                    return "成本中心退料";
                case 5:
                    return "空托盘入库";
                default:
                    return "";
            }
        }

        /// <summary>
        /// 枚举-入库单据状态
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetEmBillStatus()
        {
            var list = BaseEnum.GetCodeRulesList<EmBillStatus>();

            if (list != null)
            {
                return Ok(BaseResult.Result(list, "获取成功！", "200"));
            }
            return Ok(BaseResult.Result(null, "获取失败！", "500"));
        }

        /// <summary>
        /// 枚举-入库单据类型
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetEmInBillType()
        {
            var list = BaseEnum.GetCodeRulesList<EmInBillType>();

            if (list != null)
            {
                return Ok(BaseResult.Result(list, "获取成功！", "200"));
            }
            return Ok(BaseResult.Result(null, "获取失败！", "500"));
        }
        MemoryStream ProcessExcelData()
        {
            //模块从表中读取的数据
            List<TReceivingOrderDetail> list = new List<TReceivingOrderDetail>();
            list = TReceiving.GetTReceivingOrderDetailExcel();
            // 已经读取出了正确的数据后
            //创建Excel对象把数据赋值到对象中
            IWorkbook workbook = new XSSFWorkbook(); // Excel对象
            ISheet sheet1 = workbook.CreateSheet("入库单");  // 创建Excel中的表对象
                                                          //表头
            IRow row0 = sheet1.CreateRow(0);  // 在sheet1表格中创建第0行
            row0.CreateCell(0).SetCellValue("单号"); // 在sheet1表格中第0行创建第0列，并且在给这个单元格赋值
            row0.CreateCell(1).SetCellValue("单据类型");
            row0.CreateCell(2).SetCellValue("单据状态");
            row0.CreateCell(3).SetCellValue("货主");
            row0.CreateCell(4).SetCellValue("物料名称");
            row0.CreateCell(5).SetCellValue("物料号");
            row0.CreateCell(6).SetCellValue("批次号");
            row0.CreateCell(7).SetCellValue("任务数量");
            row0.CreateCell(8).SetCellValue("实际收到数量");
            row0.CreateCell(9).SetCellValue("计量单位");
            row0.CreateCell(10).SetCellValue("包装数量");
            row0.CreateCell(11).SetCellValue("已组垛数量");
            row0.CreateCell(12).SetCellValue("有效期");
            row0.CreateCell(13).SetCellValue("生产日期");
            row0.CreateCell(14).SetCellValue("出厂日期");
            row0.CreateCell(15).SetCellValue("逻辑分区");
            row0.CreateCell(16).SetCellValue("订单来源");
            row0.CreateCell(17).SetCellValue("创建用户");
            row0.CreateCell(18).SetCellValue("创建时间");
            row0.CreateCell(19).SetCellValue("提交人");
            row0.CreateCell(20).SetCellValue("提交时间");
            row0.CreateCell(21).SetCellValue("审核(驳回)人");
            row0.CreateCell(23).SetCellValue("审核(驳回)时间");
            var rowIndex = 1;
            foreach (var item in list)
            {
                var Sta = "";//0-新建;1-已启动;2-作业中;3-已完成;4-强制完成;5-暂停;6-失效；7-异常
                if (item.Status == 0)
                {
                    Sta = "新建";
                }
                if (item.Status == 1)
                {
                    Sta = "已启动";
                }
                if (item.Status == 2)
                {
                    Sta = "作业中";
                }
                if (item.Status == 3)
                {
                    Sta = "已完成";
                }
                if (item.Status == 4)
                {
                    Sta = "强制完成";
                }
                if (item.Status == 5)
                {
                    Sta = "暂停";
                }
                if (item.Status == 6)
                {
                    Sta = "失效";
                }
                if (item.Status == 7)
                {
                    Sta = "异常";
                }
                var sType = "";//0-手动建单；1-ERP;2-MES;3-SAP
                if (item.SourceType == 0)
                {
                    sType = "手动建单";
                }
                if (item.SourceType == 1)
                {
                    sType = "ERP";
                }
                if (item.SourceType == 2)
                {
                    sType = "SAP";
                }
                IRow row = sheet1.CreateRow(rowIndex);
                row.CreateCell(0).SetCellValue(item.OrderSn);
                row.CreateCell(1).SetCellValue((double)item.BillType);
                row.CreateCell(2).SetCellValue(Sta);
                row.CreateCell(3).SetCellValue(item.OwnerName);
                row.CreateCell(4).SetCellValue(item.MaterialName);
                row.CreateCell(5).SetCellValue(item.MaterialCode);
                row.CreateCell(6).SetCellValue(item.BatchNo);
                row.CreateCell(7).SetCellValue((double)item.Qty);
                row.CreateCell(8).SetCellValue((double)item.ReceivedQty);
                row.CreateCell(9).SetCellValue(item.UnitName);
                row.CreateCell(9).SetCellValue((double)item.PackagedQty);
                row.CreateCell(9).SetCellValue((double)item.StackedQty);
                row.CreateCell(9).SetCellValue(item.ExpireDate.ToString());
                row.CreateCell(9).SetCellValue(item.ProductDate.ToString());
                row.CreateCell(9).SetCellValue(item.OutFactoryDate.ToString());
                row.CreateCell(9).SetCellValue(item.LogicalPartName);
                row.CreateCell(9).SetCellValue(sType);
                row.CreateCell(9).SetCellValue(item.CreateUserName);
                row.CreateCell(9).SetCellValue(item.CreateDate);
                row.CreateCell(9).SetCellValue(item.SubmitUserName);
                row.CreateCell(9).SetCellValue(item.SubmitDate.ToString());
                row.CreateCell(9).SetCellValue(item.AuditUserName);
                row.CreateCell(9).SetCellValue(item.AuditDate.ToString());
                rowIndex++;
            }
            MemoryStream ms = new MemoryStream();
            workbook.Write(ms);

            return ms;
        }
        /// <summary>
        /// 下载入库单号
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public FileContentResult TreceExcel()
        {
            MemoryStream ms = ProcessExcelData();
            byte[] fileBytes = ms.ToArray();
            return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, "入库单.xlsx"); //关键语句
        }

        /// <summary>
        /// 生成条形码
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult BarCodeBuild(int id)
        {
            if(id<=0)
            {
                return Ok(BaseResult.Result("400", "Id有误！"));
            }
            var receivingOrderDetail = TReceiving.GetTReceivingOrderDetailById(id);
            if (receivingOrderDetail is null)
            {
                return Ok(BaseResult.Result(null, "入库单不存在！", "500", 0));
            }
            if (!receivingOrderDetail.Qty.HasValue || receivingOrderDetail.Qty < 1)
            {
                return Ok(BaseResult.Result(null, "入库单数量必须大于1！", "500", 0));
            }
            int qty = Convert.ToInt32(receivingOrderDetail.Qty);
            
            var res = 0;
            if (TReceivingGoodsDetailRepository.GetReceivingGoodsDetailList(id) is not null)
            {
                res = TReceivingGoodsDetailRepository.GetReceivingGoodsDetailList(id).Count();
            }
            if (res > 0 && res == qty)
            {
                return Ok(BaseResult.Result(res, "", "200"));
            }
            string baseBarCode = receivingOrderDetail.MaterialCode + DateTime.Now.ToString("yyyyMMdd");
            int count = Convert.ToInt32(qty - res);
            List<TReceivingGoodsDetail> goodsDetailData = new List<TReceivingGoodsDetail>();
            Random random = new Random();
            int randomNumber = random.Next(100000, 999999);
            for (int i = 0; i < count; i++)
            {
                string barcode = baseBarCode + randomNumber + ((res + i + 1) / 1000m).ToString("f3").Replace(".", "");
                goodsDetailData.Add(new TReceivingGoodsDetail()
                {
                    Barcode = barcode,
                    BarcodeRange = "",
                    CreateDate = DateTime.Now,
                    IsSku = false,
                    SkuNum = 1,
                    OrderDetailId = receivingOrderDetail.Id,
                    Status = 0,
                });
            }
            if (TReceivingGoodsDetailRepository.AddReceivingGoodsDetail(goodsDetailData))
            {
                return Ok(BaseResult.Result(goodsDetailData,"生成条码成功！", "200"));
            }
            return Ok(BaseResult.Result(null, "生成条码失败！", "500", 0));
        }

        /// <summary>
        /// 导出编码
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GenerateExcel(int orderDetailId)
        {
            if (orderDetailId <= 0)
            {
                return Ok(BaseResult.Result("400", "Id有误！"));
            }
            var list = TReceivingGoodsDetailRepository.GetReceivingGoodsDetailList(orderDetailId);
            if (list.Count <= 0)
            {
                return Ok(BaseResult.Result(null, "导出失败！", "500", 0));
            }
            // 创建Excel文件和工作簿
            var package = new ExcelPackage();
            var worksheet = package.Workbook.Worksheets.Add("Sheet1");
            // 添加表头
            worksheet.Cells[1, 1].Value = "物料条码";
            // 添加数据行
            int row = 2;
            foreach (var item in list)
            {
                worksheet.Cells[row, 1].Value = item.Barcode;
                row++;
            }
            // 自适应列宽
            worksheet.Cells.AutoFitColumns();
            // 返回Excel文件
            var stream = new MemoryStream(package.GetAsByteArray());
            return new FileStreamResult(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
            {
                FileDownloadName = "货品条码" + list[0].Barcode + ".xlsx"
            };

        }

        /// <summary>
        /// 采购收货单接口
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddTPurchaseReceipt(PurchaseReceiptDto dto)
        {
            if (dto == null)
            {
                return Ok(BaseResult.Result(false, "请求参数有误", "500"));
            }
            var IsOk = TReceivingGoodsDetailRepository.AddTPurchaseReceipt(dto);
            if (IsOk)
            {
                return Ok(BaseResult.Result(true, "添加成功", "200"));
            }
            return Ok(BaseResult.Result(true, "添加失败", "500"));

        }


        /// <summary>
        /// 生产订单接口
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddProductionOrder(ProductionOrderDto dto)
        {
            if (dto == null)
            {
                return Ok(BaseResult.Result(false, "请求参数有误", "500"));
            }
            var IsOk = TReceivingGoodsDetailRepository.AddProductionOrder(dto);
            if (IsOk)
            {
                return Ok(BaseResult.Result(true, "添加成功", "200"));
            }
            return Ok(BaseResult.Result(true, "添加失败", "500"));

        }

        /// <summary>
        /// 生产退料单接口
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddProductionMaterilas(ProductionMaterilasDto dto)
        {
            if (dto == null)
            {
                return Ok(BaseResult.Result(false, "请求参数有误", "500"));
            }
            var IsOk = TReceivingGoodsDetailRepository.AddProductionMaterilas(dto);
            if (IsOk)
            {
                return Ok(BaseResult.Result(true, "添加成功", "200"));
            }
            return Ok(BaseResult.Result(true, "添加失败", "500"));

        }

        /// <summary>
        /// 销售订单退货接口
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddSalesOrderReturn(SalesOrderReturnDto dto)
        {
            if (dto == null)
            {
                return Ok(BaseResult.Result(false, "请求参数有误", "500"));
            }
            var IsOk = TReceivingGoodsDetailRepository.AddSalesOrderReturn(dto);
            if (IsOk)
            {
                return Ok(BaseResult.Result(true, "添加成功", "200"));
            }
            return Ok(BaseResult.Result(true, "添加失败", "500"));

        }
    }
}
